package com.tanhua.dubbo.api;

import com.tanhua.dubbo.api.mongo.MovementApi;
import com.tanhua.dubbo.async.TimeLineService;
import com.tanhua.dubbo.utils.IdWorker;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.MovementTimeLine;
import com.tanhua.model.vo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@DubboService
@Slf4j
public class MovementApiImpl implements MovementApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private TimeLineService timeLineService;

    /**
     * 发布动态
     *
     * @param pojo
     */
    @Override
    public void add(Movement pojo) {
        long timeMillis = System.currentTimeMillis();
        //a. 添加到动态表, 得到动态的id
        // 设置pid, idWorker.getNextId("movement") 这里的字符串movement不能修改，跟后第11天的推荐系统有关
        pojo.setPid(idWorker.getNextId("movement"));
        // 设置发布的时间
        pojo.setCreated(timeMillis);
        mongoTemplate.insert(pojo);
        //得到动态的id
        ObjectId movementId = pojo.getId();
        //b. 查询登录用户的好友列表
        Long loginUserId = pojo.getUserId();
        // 异步处理添加好友时间线表记录
        timeLineService.saveTimeline(loginUserId, movementId, timeMillis);
        log.debug("动态发布完成");
    }

    /**
     * 通过用户id分页查询动态
     *
     * @param page
     * @param pageSize
     * @param searchUserId
     * @return
     */
    @Override
    public PageResult findPageByUserId(Long page, Long pageSize, Long searchUserId) {
        //1.构建查询条件
        Query query = new Query(Criteria.where("userId").is(searchUserId));
        //2.统计总数
        long total = mongoTemplate.count(query, Movement.class);
        //3.总数大于start
        Long start = (page-1) * pageSize;
        List<Movement> list = new ArrayList<>();
        if(total > start) {
            //4.设置分页参数
            query.skip(start).limit(pageSize.intValue());
            //5.按created降序
            query.with(Sort.by(Sort.Order.desc("created")));
            //6.查询动态表
            list = mongoTemplate.find(query, Movement.class);
        }
        //7.构建pageResult返回
        return new PageResult(page, pageSize,total, list);
    }

    /**
     * 通过登录用户id分页查询朋友们发布的动态
     *
     * @param page
     * @param pageSize
     * @param loginUserId
     * @return
     */
    @Override
    public PageResult findFriendMovements(Long page, Long pageSize, Long loginUserId) {
        //1. 先查询时间线表，条件friendId=loginUserId
        //1.1 构建条件
        Query timelineQuery = new Query(Criteria.where("friendId").is(loginUserId));
        //1.2 统计总数
        long total = mongoTemplate.count(timelineQuery, MovementTimeLine.class);
        //1.3 计算start
        long start = (page-1) * pageSize;
        List<Movement> movementList = new ArrayList<>();
        //1.4 total>start
        if(total > start) {
            //1.5 设置分页
            timelineQuery.skip(start).limit(pageSize.intValue());
            //1.6 时间降序
            timelineQuery.with(Sort.by(Sort.Order.desc("created")));
            //1.7 分页查询得到结果list
            List<MovementTimeLine> timeLineList = mongoTemplate.find(timelineQuery, MovementTimeLine.class);

            //2. 获取动态ids
            List<ObjectId> movementIds = timeLineList.stream().map(MovementTimeLine::getMovementId).collect(Collectors.toList());
            //3. 查询动态表，得到动态信息
            //3.1 构建动态表查询条件
            Query query = new Query(Criteria.where("_id").in(movementIds));
            //3.2 降时间降序
            query.with(Sort.by(Sort.Order.desc("created")));
            //3.3 查询动态表
            movementList = mongoTemplate.find(query, Movement.class);
        }
        //4. 构建pageResult返回
        return new PageResult(page,pageSize,total,movementList);
    }

    /**
     * 通过pid查询动态信息
     *
     * @param pids
     * @return
     */
    @Override
    public List<Movement> findPids(List<Long> pids) {
        //1. 构建查询条件
        Query query = new Query(Criteria.where("pid").in(pids));
        //2. 查询动态表
        List<Movement> movementList = mongoTemplate.find(query, Movement.class);
        return movementList;
    }

    /**
     * 随机10条动态
     *
     * @return
     */
    @Override
    public List<Movement> randomMovement() {
        Query query = new Query();
        long total = mongoTemplate.count(query, Movement.class);
        if(total < 10){
            return mongoTemplate.find(query,Movement.class);
        }else{
            long start = RandomUtils.nextLong(0,total-9);
            query.skip(start).limit(10);
        }
        return mongoTemplate.find(query,Movement.class);
    }

    /**
     * 通过id查询
     *
     * @param movementId
     * @return
     */
    @Override
    public Movement findById(String movementId) {
        return mongoTemplate.findById(new ObjectId(movementId), Movement.class);
    }
}
